import {PrismaClient, Prisma} from '@prisma/client';
import {faker} from '@faker-js/faker';
import bcrypt from 'bcryptjs';

const client = new PrismaClient();

// DO NOT init category or delete data about it
const needInit = {
  category: false, user: false, account: false, 
  limit: false, bill: true, note: true
};

function randNum(min: number, max: number) {
  const base = Math.floor(Math.random() * (max - min + 1));
  return base + min;
}

async function seedCategory() {
  const category: Array<Prisma.categoryCreateInput> = [
    {categoryID: 0, categoryName: 'income'},
    {categoryID: 1, categoryName: 'food'},
    {categoryID: 2, categoryName: 'drink'},
    {categoryID: 3, categoryName: 'transportation'},
    {categoryID: 4, categoryName: 'shopping'},
    {categoryID: 5, categoryName: 'entertainment'},
    {categoryID: 6, categoryName: 'housing'},
    {categoryID: 7, categoryName: 'electronic'},
    {categoryID: 8, categoryName: 'medical'},
    {categoryID: 9, categoryName: 'misc'}
  ];
  return await client.category.createMany({data: category});
}

async function seedUser() {
  const exampleStr = '0123456789';
  const userData: Array<Prisma.userCreateManyInput> = [];
  for(let i = 0; i <= 4; i++ ){
    const userDetail = exampleStr.slice(i, i + 6);
    userData.push({
      userName: faker.name.fullName(),
      email: `${userDetail}@qq.com`,
      password: bcrypt.hashSync(userDetail, bcrypt.genSaltSync())
    });
  }
  console.log(userData);
  return await client.user.createMany({data: userData});
}

async function seedAccount() {
  const userData = await client.user.findMany();
  const accountData: Array<Prisma.accountCreateManyInput> = userData.map((user) => {
    const accountType = randNum(1, 3);
    let accountName = 'undefined';
    switch(accountType) {
    case 1: accountName = 'cash'; break;
    case 2: accountName = 'card'; break;
    case 3: accountName = 'epay'; break;
    }
    return {
      priority: 1,
      accountName: accountName,
      type: accountType,
      ownerID: user.userID
    };
  });
  return await client.account.createMany({ data: accountData });
}

async function seedLimit() {
  const userData = await client.user.findMany();
  const limitData: Array<Prisma.limitCreateManyInput> = userData.map((user) => ({
    cost: randNum(1000, 3000),
    ownerID: user.userID
  }));
  return await client.limit.createMany({data: limitData});
}

async function seedBill() {
  const accountData = await client.account.findMany();
  const categories = await client.category.findMany();
  const billData: Array<Prisma.billCreateManyInput> = accountData.map((account) => {
    const typeID = randNum(0, 9);
    let tagName = categories.find((elem) => (elem.categoryID === typeID))?.categoryName;
    tagName = tagName ? tagName : 'empty';
    const costValue = Number(faker.commerce.price(1, 2000));
    return {
      time: faker.date.recent(3),
      cost: costValue,
      expression: costValue.toString(),
      billType: typeID,
      tag: tagName,
      accountID: account.accountID
    };
  });
  return await client.bill.createMany({ data: billData });
}

async function seedNote() {
  const userData = await client.user.findMany();
  const noteData: Array<Prisma.noteCreateManyInput> = userData.map((user) => ({
    ownerID: user.userID,
    title: faker.word.adjective(),
    content: faker.hacker.phrase(),
    date: faker.date.recent()
  }));
  return await client.note.createMany({ data: noteData});
}

if(needInit.category) {
  const res = await seedCategory();
  console.log('seed category: ');
  console.log(res);
}
if(needInit.user) {
  const res = await seedUser();
  console.log('seed user: ');
  console.log(res);
}
if(needInit.account) {
  const res = await seedAccount();
  console.log('seed account: ');
  console.log(res);
}
if(needInit.limit) {
  const res = await seedLimit();
  console.log('seed limit: ');
  console.log(res);
}
if(needInit.bill) {
  console.log('seed bill: ');
  for(let i = 0; i < 2; i++){
    const res = await seedBill();
    console.log(res);
  }
}
if(needInit.note){
  console.log('seed note: ');
  for(let i = 0; i < 2; i++){
    const res = await seedNote();
    console.log(res);
  }
}